package com.chenjiaru.thread.atomic;

import com.chenjiaru.thread.util.ThreadUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * atomic类型变量使用
 */
@Data
@Slf4j
public class AtomicDemo {


    public volatile static Integer ticket = 20;
    public static AtomicInteger atomicTicket = new AtomicInteger(20);

    public static void main(String[] arr) {
        atomic();
    }

    /**
     * 使用原子性的变量（能保证线程安全，结果就类似乐观锁）
     */
    private static void atomic() {
        // 10条线程去售票
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(() -> {
                while (true) {
                    if (AtomicDemo.atomicTicket.get() <= 0) {
                        break;
                    }
                    log.info("出售一张票，余票={}", AtomicDemo.atomicTicket.decrementAndGet());
                    ThreadUtil.mySleep(300);
                }
            });
            thread.setName("售票员"+i);
            thread.start();
        }
    }

    /**
     * 没有锁
     * 1.有线程安全问题
     * 2.不能保证原子性，在字节码及底层，--AtomicDemo.ticket被抽象为三个操作 即先取值，再自减，再赋值操作没有同时成功
     */
    private static void nolock() {
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(() -> {
                while (true) {
                    if (AtomicDemo.ticket <= 0) {
                        break;
                    }
                    log.info("出售一张票，余票={}", --AtomicDemo.ticket);
                    ThreadUtil.mySleep(200);
                }
            });
            thread.setName("售票员"+i);
            thread.start();
        }
    }

}
